var { Point } = require("./Point.js");

// var k1 = 1
class Plot {
  static viewv = {
    left: 0,
    top: 0,
    k1: 1,
    xSin: 0, // Math.PI
    ySin:0,
  };
  /**
   * Creates an instance of Plot.
   * 画布，所有被画出来的元素都append到这个container
   * @memberof Plot
   * @param canvasDom {HTMLCanvasElement}
   */
  constructor(canvasDom) {

    /**
     * @type {HTMLCanvasElement}
     */
    this.container = canvasDom; //
    canvasDom.width = document.body.clientWidth;
    canvasDom.height = document.body.clientHeight;
    //  初始化长宽
    canvasDom.style.width = document.body.clientWidth + "px";
    canvasDom.style.height = document.body.clientHeight + "px";
    this.context = this.container.getContext("2d");
    //原点
    this.radius = 2; // 点的半径
    /**
     * @type {Point}
     */
    this.origin = new Point(0, 0);
    // this.context.setTransform

    this.context.translate(this.container.width / 2, this.container.height / 2);
    this.context.rotate(Math.PI * 1.5);
    //坐标颜色
    this.baseLineColor = "black";
    //画笔颜色
    this.brushColor = "red";
    //画笔粗细

    this.gain = 1;
    // this.drawCoordinate();
    this.initKeyEvent();
    this.points = [];
    this.lines = [];
    this.clean()
    //baseLineX，baseLineY保存坐标线，用于坐标移位
    //初始化方法，设置画布，原点位置，坐标线颜色，画笔颜色，画笔粗细
    //  var rect = canvas.getBoundingClientRect();
  }

  init(baseLineColor, brushColor) {
    this.baseLineColor = baseLineColor;
    this.brushColor = brushColor;
    this.drawCoordinate();
    
  }
  /**
   * 原点
   * @param {any} p
   * @memberof Plot
   */
  setOPoint(p) {
    if (p.x != undefined && p.y != undefined) this.origin = p;
    this.context.translate(
      this.container.width / 2 + p.x,
      this.container.height / 2 + p.y
    );
    this.drawCoordinate();
  }
  //画坐标线
  drawCoordinate() {
    var height = this.container.height;
    var width = this.container.width;
    this.line(
      { x: 0, y: -height / 2 }, //this.container.width / 2
      { x: 0, y: height / 2 }
    );
    this.line({ x: -width, y: 0 }, { x: width, y: 0 });
  }
  //清理画布，移走所有对象
  clean() {
    // this.context.fillStyle = "#000000";
    // this.context.beginPath(); 
    // this.container.width/2
    // this.context.fillRect(-Infinity, -Infinity, Infinity, Infinity);
    // this.context.closePath();
    // console.log(-this.container.width / 2, -this.container.height / 2, 2 * this.container.width, 2 * this.container.height)
    // this.context.clearRect(-this.container.width / 2, -this.container.height / 2, 2 * this.container.width, 2 * this.container.height);
    // this.drawCoordinate();
    this.fillColor([0, 1, 0, 255])
  }
  
  fillColor(color4) {
    var { context } = this;
    let { width: w, height: h } = this.container
    var a = context.getImageData(0, 0, w, h)
    var data = a.data
    var [cr, cg, cb, ca] = color4
    for (let index = 0, len = data.length; index < len;) {
      data[index++] = cr
      data[index++] = cg
      data[index++] = cb
      data[index++] = ca
    }
    context.putImageData(a, 0, 0);
  }

  drawColor(cb) {
    var { context } = this;
    let { width: w, height: h } = this.container
    var a = context.getImageData(0, 0, w, h)
    context.putImageData(a, 0, 0);
  }
  
  /**
   * // 画点，相对原点  //div 绘制点 
   * @param {*} p 
   * @param {*} color 
   */
  drawDot(p, color) {
    if (!(p.x != undefined && p.y != undefined))
      return; //校验
    this.context.beginPath();
    this.context.arc(p.y, p.x, this.radius, 0, Math.PI * 2, false); //x ,y r ,stangle
    this.context.closePath();
    this.context.fillStyle = color || this.brushColor;
    //本来这里最初使用的是red，
    this.context.fill();
  }
  /**
   * 
   *   //画线从(x0,y0)到(x1,y1)
   * @param {*} point0 
   * @param {*} point1 
   * @param {string} color 
   */
  line(point0, point1, color = "red") {
    //竖线
    this.context.lineWidth = this.radius / 2;
    this.context.save();
    this.context.beginPath();
    this.context.moveTo(point0.y, point0.x); //将画笔移到x0,y0处//point0.x,
    this.context.lineTo(point1.y, point1.x); //从x1,y1到x2,y2画条线
    this.context.strokeStyle = color;
    this.context.stroke(); //画线
    this.context.restore();
  }
  drawPoint(p, color) {
    this.points.push([p, color]);
    this.drawDot(p, color)
  }
  drawNodeSet(nodes, color = "red") {
    //绘制节点集合
    // if (nodes) 
    // this.points = this.points.concat(nodes);
    for (var index in nodes) {
      this.drawDot(nodes[index], color);
    }
  }
  drawLine(point0, point1) {
    this.lines.push([point0, point1]);
    this.line(point0, point1);
  }
  reDraw() {
    this.points.forEach((params) => {
      this.drawDot.apply(this, params)
    });
    this.lines.forEach((params) => {
      this.line.apply(this, params)
    })
  }

  initKeyEvent() {
    let movd = 5;
    
    console.log(" // 38 40 |37 39 // 上下 左右  [] 放大缩小")
    document.addEventListener("keydown", e => {
      var viewv = Plot.viewv
      //this.origin.y -= movd * k1;
      var centerX = viewv.left + this.container.width / 2 * viewv.k1;
      var centerY = viewv.top + this.container.height / 2 * viewv.k1;
      switch (e.which) {
        case 38:
          this.context.translate(-movd * viewv.k1, 0);
          viewv.top -= movd * viewv.k1;
          break;
        case 40:
          this.context.translate(movd *viewv. k1, 0);
          viewv.top += movd * viewv.k1;
          break;
        case 37:
          this.context.translate(0, -movd *viewv. k1);
          viewv.left -= movd * viewv.k1;
          break;
        case 39:
          this.context.translate(0, movd * viewv.k1);
          viewv.left += movd * viewv.k1;
          break;
        case 221:
          this.context.scale(0.8, 0.8);
          this.radius /= 0.8
          viewv. k1 *= 0.8;
          viewv.top = centerY - viewv.k1 * this.container.height / 2;
          viewv.left = centerX - viewv.k1 * this.container.width / 2;
          break;
        case 219:
          this.context.scale(1 / 0.8, 1 / 0.8);
          this.radius *= 0.8
          viewv.k1 *= 1.25;
          viewv.top = centerY - viewv.k1 * this.container.height / 2;
          viewv.left = centerX - viewv.k1 * this.container.width / 2;
          break;
        case 97:
          viewv.xSin = (viewv.xSin + 0.01) % Math.PI;
          this.clean();
          break
        case 98:
          viewv.xSin = (viewv.xSin - 0.01) % Math.PI;
        case 99:
          viewv.ySin = (viewv.ySin + 0.01) % Math.PI;
          break
        case 98:
          viewv.ySin = (viewv.ySin - 0.01) % Math.PI;
        break
      }

      this.clean();
      this.reDraw();
    });
  }
  /**
   * @param {{x:number,y:number}[]} list
   */
  drawList(list) {
    var viewv = Plot.viewv
    var k1 = viewv.k1
    var a, p
    this.COLOR = 255
    var { context, COLOR } = this;
    context.shadowColor = "#000"
    let { width: w, height: h } = this.container
    let b = (a = context.getImageData(0, 0, w, h)).data; // let
    for (let index = 0, len = b.length; index < len;) {
      b[index++] = 0
      b[index++] = 0
      b[index++] = 0
      b[index++] = 255
    }
    let dlen = b.length;
    for (let i = 0, len = list.length; i < len; i++) {
      p = list[i];
      let x13 = (p.x - viewv.left) / k1;
      let y13 = (p.y - viewv.top) / k1;
      if (x13 < 0 || x13 >= w || y13 < 0 || y13 >= h) continue;
      let n = ~~(x13 + ~~y13 * w) * 4;
      if (n < 0 || n >= dlen - 3) {
        continue;
      }
      // @ts-ignore
      b[n] = b[n + 1] = b[n + 2] = p.COLOR || COLOR, b[n + 3] = 255
      if (!p.e) {
        b[n + 1] = b[n + 2] = p.COLOR = 0
      }
    }
    context.putImageData(a, 0, 0);
  }
  
  /**
   * 
   * @param {number[]} color 
   */
  pickColor(color, diff = 1) {
    var data = this.context.getImageData(0, 0, this.container.width, this.container.height).data;
    var list = [];
    var { k1, left, top } = Plot.viewv
    var w = this.container.width;
    for (let index = 0, len = data.length; index < len; index += 4) {
      var w0 = (index / 4) % w;
      var h0 = ((index / 4) - w0) / w;
      // && data[index + 1] == color[1] && data[index + 2] == color[2] && data[index + 3] == color[3]
      // todo
      if (Math.abs(data[index] - color[0]) <= diff
        && Math.abs(data[index + 1] - color[1]) <= diff
        && Math.abs(data[index + 2] - color[2]) <= diff
        && Math.abs(data[index + 3] - color[3]) <= diff
      ) {
        list.push({ x: w0 * k1 + left, y: h0 * k1 + top })
      }
    }
    return list
  }
  get center() {
    var { k1, left, top } = Plot.viewv
    return { x: this.container.width / 2 * k1 + left, y: this.container.height * k1 + left }
  }
  /**
   * 
   * @param {{x,y,z}[]} list 
   */
  draw3D(list) {
    var view = Plot.viewv;
    var list2d = [];
    for (let index = 0; index < list.length; index++) {
      var obj = list[index];
      var obj2d = {}
      obj2d.x = obj.z * Math.sin(view.xSin) + obj.x * Math.cos(view.xSin);
      obj2d.y = obj.z * Math.sin(view.ySin) + obj.y * Math.cos(view.ySin);
      list2d.push(obj2d)
    }
    this.drawList(list2d)
  }
}
module.exports = { Plot };
